<!doctype html>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="./bower_components/jquery/dist/jquery.js"></script>
</head>
<body>

<div id="log"></div>

<script type="text/javascript">
    this.log = function(message) {
        $('#log').append('<p>' + message + '</p>');
    }

    var Queue = function() {
        var lastPromise = null;
        this.add = function(obj, method, args, context) {
            var methodDeferred = $.Deferred();
            var queueDeferred = this.setup();
            if(context === undefined) { context = obj; }

            // execute next queue method
            queueDeferred.done(function() {


                // call actual method and wrap output in deferred
                setTimeout(function() {
                    obj[method].apply(context, args);
                    methodDeferred.resolve();
                }, 100);


            });
            lastPromise = methodDeferred.promise();
        };

        this.setup = function() {
            var queueDeferred = $.Deferred();

            // when the previous method returns, resolve this one
            $.when(lastPromise).always(function() {
                queueDeferred.resolve();
            });

            return queueDeferred.promise();
        }
    };

    var q = new Queue();
    q.add(this, 'log', ['one']);
    q.add(this, 'log', ['two']);
    q.add(this, 'log', ['three']);
    setTimeout(function(){
        q.add(this, 'log', ['four']);
    }, 2000);
</script>
</body>
</html>